/*
 * Created on Mar 17, 2010
 */
package ro.letsdoitromania;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.StringItem;
import com.mgmaps.tools.MiscTools;
import com.mgmaps.tools.StringTools;
import com.mgmaps.utils.LS;
import com.nutiteq.components.WgsPoint;

public class TrashPointData {
  private int id;
  
  private Date dateTime;
  private WgsPoint point;
  private String description;
  private double length;
  private double width;
  private double height;
  
  private boolean roadDifficult;
  private boolean roadDifficultRain;
  
  private boolean dispersed;
  private double bagEq;

  public static final int NUM_PERCENTAGES = 8;
  private static final String[] PERC_TAGS = {
    "Organic", "Glass", "Metal", "Plastic", "Carton", "Rubber", "Volume", "RawMatterials"
  };
  private static final int[] PERC_REORDER = { 4, 1, 2, 0, 3, 7, 5, 6 }; 
  private int[] perc;
  
  private byte[][] photos;
  
  private static StringItem descItem;
  private static StringItem locItem;
  private static StringItem detItem;
  private static StringItem photo1Item;
  private static StringItem photo2Item;
  
  // 0 = Organic = not recyclable
  // 1 = Glass = glass
  // 2 = Metal = metal
  // 3 = Plastic = plastic
  // 4 = Carton = paper
  // 5 = RawMatterials = construction
  // 6 = Rubber = rubber
  // 7 = Volume = big volume;
  
  /**
   * Contructor for TrashPointData.
   */
  public TrashPointData(int id, Date date, WgsPoint point, String desc, 
      double length, double width, double height, boolean dif, boolean difRain,
      boolean dispersed, double bagEq, int[] perc) {
    this.id = id;
    this.dateTime = date;
    this.point = point;
    this.description = desc;
    this.length = length;
    this.width = width;
    this.height = height;
    this.roadDifficult = dif;
    this.roadDifficultRain = difRain;
    this.dispersed = dispersed;
    this.bagEq = bagEq;
    this.perc = new int[perc.length];
    for (int i=0; i<perc.length; i++)
      this.perc[i] = perc[i];
    adjustPercentages();
  }
  
  /**
   * Read from RecordStore.
   *
   * @param dis input stream
   */
  public TrashPointData(int id, DataInputStream dis) throws IOException {
    this.id = id;
    
    dateTime = new Date(dis.readLong());
    double lon = dis.readDouble();
    double lat = dis.readDouble();
    point = new WgsPoint(lon, lat);
    description = dis.readUTF();
    length = dis.readDouble();
    if (Settings.propsVersionOld >= 2)
      width = dis.readDouble();
    else
      width = length;
    height = dis.readDouble();
    
    roadDifficult = dis.readBoolean();
    roadDifficultRain = dis.readBoolean();
    
    if (Settings.propsVersionOld >= 2) {
      dispersed = dis.readBoolean();
      bagEq = dis.readDouble();
    }
    
    perc = new int[NUM_PERCENTAGES];
    for (int i=0; i<NUM_PERCENTAGES; i++)
      perc[i] = dis.readInt();
    adjustPercentages();

    if (Settings.propsVersionOld == 3)
      dis.readBoolean();
    
    // load photos
    if (Settings.propsVersionOld >= 6) {
      int numPhotos = dis.readInt();
      photos = new byte[numPhotos][];
      for (int i=0; i<numPhotos; i++) {
        int sz = dis.readInt();
        photos[i] = new byte[sz];
        dis.read(photos[i], 0, sz);
      }
    }
  }
  
  /**
   * Adjust percentages to always sum up to 100%.
   */
  private void adjustPercentages() {
    int totalPerc = 0;
    for (int i=0; i<NUM_PERCENTAGES; i++)
      totalPerc += perc[i];
    if (totalPerc == 0)
      return;
    
    for (int i=0; i<NUM_PERCENTAGES; i++)
      perc[i] = (int) MiscTools.round((double) perc[i]*100/totalPerc);
  }
  
  public void write(DataOutputStream dos) throws IOException {
    dos.writeLong(dateTime.getTime());
    dos.writeDouble(point.getLon());
    dos.writeDouble(point.getLat());
    dos.writeUTF(description);
    dos.writeDouble(length);
    dos.writeDouble(width);
    dos.writeDouble(height);
    
    dos.writeBoolean(roadDifficult);
    dos.writeBoolean(roadDifficultRain);
    
    dos.writeBoolean(dispersed);
    dos.writeDouble(bagEq);
    
    for (int i=0; i<NUM_PERCENTAGES; i++)
      dos.writeInt(perc[i]);
    
    if (photos == null)
      dos.writeInt(0);
    else {
      dos.writeInt(photos.length);
      for (int i=0; i<photos.length; i++) {
        dos.writeInt(photos[i].length);
        dos.write(photos[i]);
      }
    }
  }
  
  public String buildXML() {
    StringBuffer sb = new StringBuffer();
    sb.append("<garbage>");
    sb.append("<BagEq>" + StringTools.floatFormat(bagEq, 0) + "</BagEq>");
    sb.append("<Description>" + description + "</Description>");
    sb.append("<Diameter>0</Diameter>");
    sb.append("<Height>" + StringTools.floatFormat(height, 0) + "</Height>");
    sb.append("<ID>" + id + "</ID>");
    sb.append("<IsAccessDifficult>" + roadDifficult + "</IsAccessDifficult>");
    sb.append("<IsAccessDifficultOnRain>" + roadDifficultRain + "</IsAccessDifficultOnRain>");
    sb.append("<IsDispersed>" + dispersed + "</IsDispersed>");
    sb.append("<IsTest>" + Settings.isTest + "</IsTest>");
    sb.append("<Length>" + StringTools.floatFormat(length, 0) + "</Length>");
    sb.append("<Location><Latitude>" + point.getLat() + "</Latitude><Longitude>" + point.getLon() + "</Longitude></Location>");
    for (int i=0; i<NUM_PERCENTAGES; i++)
      sb.append("<Percentage" + PERC_TAGS[PERC_REORDER[i]] + ">" + perc[PERC_REORDER[i]] + "</Percentage" + PERC_TAGS[PERC_REORDER[i]] + ">");
    sb.append("<PostingDateTime>" + StringTools.dateTimeFormat(dateTime, "T") + "</PostingDateTime>");
    sb.append("<Width>" + StringTools.floatFormat(width, 0) + "</Width>");
    sb.append("</garbage>");
    return sb.toString();
  }
  
  public Item[] buildItems(boolean extended, int photoNum, ItemCommandListener lsn) {
    // FIX extended details
    if (descItem == null)
      descItem = new StringItem(LS.get("ldir.add.desc"), description);
    else {
      descItem.setLabel(LS.get("ldir.add.desc"));
      descItem.setText(description);
    }

    if (locItem == null)
      locItem = new StringItem(LS.get("ldir.add.loc"), point.toString());
    else {
      locItem.setLabel(LS.get("ldir.add.loc"));
      locItem.setText(point.toString());
    }
    
    String details = "";
    details += LS.get("ldir.add.length") + " " + StringTools.floatFormat(length, 0) + "m\n";
    details += LS.get("ldir.add.width") + " " + StringTools.floatFormat(width, 0) + "m\n";
    details += LS.get("ldir.add.height") + " " + StringTools.floatFormat(height, 0) + "m\n";
    if (roadDifficult)
      details += LS.get("ldir.add.roaddif") + " " + LS.get("ldir.add.roaddifall") + "\n";
    if (roadDifficultRain)
      details += LS.get("ldir.add.roaddif") + " " + LS.get("ldir.add.roaddifrain") + "\n";
    if (dispersed) {
      details += LS.get("ldir.add.dispersed") + "\n";
      details += LS.get("ldir.add.bageq") + " " + StringTools.floatFormat(bagEq, 0) + "\n";
    }
    details += LS.get("ldir.add.perc.header");
    boolean added = false;
    for (int i=0; i<NUM_PERCENTAGES; i++)
      if (perc[i] > 0) {
        if (added)
          details += ",";
        else
          added = true;
        details += " " + perc[i] + "% " + LS.get("ldir.add.perc." + i);
      }

    if (detItem == null)
      detItem = new StringItem(LS.get("ldir.add.details"), details);
    else {
      detItem.setLabel(LS.get("ldir.add.details"));
      detItem.setText(details);
    }
    
    if (extended && photoNum > 0 && !Settings.isBlackberry) {
      if (photoNum >= 1) {
        if (photo1Item == null) {
          photo1Item = new StringItem("", LS.get("app.command.photo1"), Item.BUTTON);
          photo1Item.setDefaultCommand(Commands.cinstance.photo1CommandItem);
          photo1Item.setItemCommandListener(lsn);
        }
      }
      if (photoNum >= 2) {
        if (photo2Item == null) {
          photo2Item = new StringItem("", LS.get("app.command.photo2"), Item.BUTTON);
          photo2Item.setDefaultCommand(Commands.cinstance.photo2CommandItem);
          photo2Item.setItemCommandListener(lsn);
        }
      }
      if (photoNum == 1)
        return new Item[] { descItem, locItem, detItem, photo1Item };
      else
        return new Item[] { descItem, locItem, detItem, photo1Item, photo2Item };
    }
    else
      return new Item[] { descItem, locItem, detItem };
  }
  
  /**
   * String representation, suitable for displaying in a "list" of items.
   * @return a string
   * @see java.lang.Object#toString()
   */
  public String toString() {
    return id + " - " + StringTools.dateTimeFormat(dateTime) + " - " + description;
  }
  
  public int getID() {
    return id;
  }
  
  public WgsPoint getPoint() {
    return point;
  }
  
  public Date getDateTime() {
    return dateTime;
  }

  /**
   * Sets the value of description.
   *
   * @param description The description to set.
   */
  public void setDescription(String description) {
    this.description = description;
  }

  /**
   * Sets the value of length.
   *
   * @param diameter The length to set.
   */
  public void setLength(double length) {
    this.length = length;
  }

  /**
   * Sets the value of width.
   *
   * @param diameter The width to set.
   */
  public void setWidth(double width) {
    this.width = width;
  }

  /**
   * Sets the value of height.
   *
   * @param height The height to set.
   */
  public void setHeight(double height) {
    this.height = height;
  }

  /**
   * Sets the value of roadDifficult.
   *
   * @param roadDifficult The roadDifficult to set.
   */
  public void setRoadDifficult(boolean roadDifficult) {
    this.roadDifficult = roadDifficult;
  }

  /**
   * Sets the value of roadDifficultRain.
   *
   * @param roadDifficultRain The roadDifficultRain to set.
   */
  public void setRoadDifficultRain(boolean roadDifficultRain) {
    this.roadDifficultRain = roadDifficultRain;
  }

  /**
   * Sets the value of dispersed.
   *
   * @param dispersed The dispersed to set.
   */
  public void setDispersed(boolean dispersed) {
    this.dispersed = dispersed;
  }

  /**
   * Sets the value of bagEq.
   *
   * @param bagEq The bagEq to set.
   */
  public void setBagEq(double bagEq) {
    this.bagEq = bagEq;
  }
  

  /**
   * Sets the value of perc.
   *
   * @param perc The perc to set.
   */
  public void setPercentages(int[] perc) {
    this.perc = perc;
    adjustPercentages();
  }

  /**
   * Getter for perc.
   *
   * @return Returns the value of perc.
   */
  public int[] getPercentages() {
    return perc;
  }

  /**
   * Getter for description.
   *
   * @return Returns the value of description.
   */
  public String getDescription() {
    return description;
  }

  /**
   * Getter for length.
   *
   * @return Returns the value of length.
   */
  public double getLength() {
    return length;
  }

  /**
   * Getter for width.
   *
   * @return Returns the value of width.
   */
  public double getWidth() {
    return width;
  }

  /**
   * Getter for height.
   *
   * @return Returns the value of height.
   */
  public double getHeight() {
    return height;
  }

  /**
   * Getter for roadDifficult.
   *
   * @return Returns the value of roadDifficult.
   */
  public boolean isRoadDifficult() {
    return roadDifficult;
  }

  /**
   * Getter for roadDifficultRain.
   *
   * @return Returns the value of roadDifficultRain.
   */
  public boolean isRoadDifficultRain() {
    return roadDifficultRain;
  }
  
  /**
   * Getter for dispersed.
   *
   * @return Returns the value of dispersed.
   */
  public boolean isDispersed() {
    return dispersed;
  }
  

  /**
   * Getter for bagEq.
   *
   * @return Returns the value of bagEq.
   */
  public double getBagEq() {
    return bagEq;
  }
  

  /**
   * Setter for id.
   * 
   * @param id The id to set.
   */
  public void setID(int id) {
    this.id = id;
  }

}
